using LibGit2Sharp;
using LibGit2Sharp.Handlers;
using ProjectManager.Interface;
using ProjectManager.Logic.Content;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ProjectManager.Controller
{
    internal partial class GitController : IGit
    {
        public void Clone(ProjectInformation projectInformation, string name, string password)
        {
            try
            {
                // 构建凭证
                var credentials = new UsernamePasswordCredentials
                {
                    Username = name,
                    Password = password
                };

                // 使用 libgit2sharp 克隆仓库
                var cloneOptions = new CloneOptions();
                cloneOptions.FetchOptions.CredentialsProvider = (_url, _user, _cred) => credentials;
                Repository.Clone(projectInformation.Url, projectInformation.Path, cloneOptions);

                Console.WriteLine($"Successfully cloned repository to {projectInformation.Path}");
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Failed to clone repository", ex);
            }
        }

        public void Commit(ProjectInformation projectInformation, ProjectTaskInformation branchInformation, string commitName, string commitDescription)
        {
            try
            {
                using (var repo = new Repository(projectInformation.Path))
                {
                    // 获取当前分支
                    var branch = repo.Branches[branchInformation.BranchName];
                    if (branch == null)
                    {
                        throw new InvalidOperationException("Branch not found.");
                    }

                    // 创建提交
                    var signature = new Signature(new(commitName, branchInformation.Name), DateTime.Now);
                    var commitMessage = commitDescription;

                    // 提交所有更改
                    var commit = repo.Commit(commitMessage, signature, signature);

                    Console.WriteLine($"Successfully committed changes with message: {commitMessage}");
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Failed to commit changes", ex);
            }
        }

        public void CreateBranch(ProjectInformation projectInformation, string branchName)
        {
            try
            {
                using (var repo = new Repository(projectInformation.Path))
                {
                    // 获取当前分支
                    var currentBranch = repo.Head;

                    // 创建新分支
                    var newBranch = repo.CreateBranch(branchName, currentBranch.Tip);

                    // 切换到新分支
                    Commands.Checkout(repo, newBranch);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"创建分支失败: {ex.Message}", ex);
            }
        }

        public GitCommitTree GetCommitTree(ProjectInformation projectInformation, ProjectTaskInformation branchInformation)
        {
            try
            {
                using (var repo = new Repository(projectInformation.Path))
                {
                    var branch = repo.Branches[branchInformation.BranchName];

                    // 获取提交树
                    var commit = branch.Tip;
                    var commitTree = new GitCommitTree(commit.Id.ToString(), commit.Author.Name, commit.Message);

                    // 递归获取子提交
                    GetCommitTreeRecursive(commit, commitTree);

                    return commitTree;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"获取提交树失败: {ex.Message}", ex);
            }
        }

        private void GetCommitTreeRecursive(Commit commit, GitCommitTree commitTree)
        {
            foreach (var parent in commit.Parents)
            {
                var childTree = new GitCommitTree(parent.Id.ToString(), parent.Author.Name, parent.Message);
                commitTree.childTrees.Add(childTree);
                GetCommitTreeRecursive(parent, childTree);
            }
        }

        public GitCommitTree GetCurrentCommitTree(ProjectInformation projectInformation, ProjectTaskInformation branchInformation)
        {
            try
            {
                using (var repo = new Repository(projectInformation.Path))
                {
                    var branch = repo.Branches[branchInformation.BranchName];
                    var commit = branch.Tip;

                    return new GitCommitTree(commit.Id.ToString(), commit.Author.Name, commit.Message);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"获取当前提交失败: {ex.Message}", ex);
            }
        }

        public bool Pull(ProjectInformation projectInformation, ProjectTaskInformation branchInformation)
        {
            try
            {
                using (var repo = new Repository(projectInformation.Path))
                {
                    var branch = repo.Branches[branchInformation.BranchName];
                    if (branch == null)
                    {
                        throw new InvalidOperationException("Branch not found.");
                    }

                    // 获取远程仓库信息
                    var remote = repo.Network.Remotes["origin"];
                    var fetchOptions = new FetchOptions
                    {
                        CredentialsProvider = (_url, _user, _cred) => new UsernamePasswordCredentials
                        {
                            Username = branchInformation.Name,
                            Password = branchInformation.Description
                        }
                    };

                    // 拉取更新
                    // 使用 "origin" 作为远程仓库名称，传递 FetchOptions
                    var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification);
                    repo.Network.Fetch("origin", refSpecs, fetchOptions);

                    // 检查是否有更新，如果有更新则返回 true
                    return true;
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Failed to pull repository", ex);
            }
        }

        public void Push(ProjectInformation projectInformation, ProjectTaskInformation branchInformation)
        {
            try
            {
                using (var repo = new Repository(projectInformation.Path))
                {
                    // 获取指定分支
                    var branch = repo.Branches[branchInformation.BranchName];

                    // 设置推送的目标
                    var pushOptions = new PushOptions
                    {
                        CredentialsProvider = (_url, _user, _cred) => new UsernamePasswordCredentials
                        {
                            Username = "your-username",
                            Password = "your-password"
                        }
                    };

                    // 推送分支到远程
                    repo.Network.Push(branch, pushOptions);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"推送失败: {ex.Message}", ex);
            }
        }

        public void Roll(ProjectInformation projectInformation, ProjectTaskInformation branchInformation, string commitID)
        {
            try
            {
                using (var repo = new Repository(projectInformation.Path))
                {
                    // 查找指定的提交
                    var commit = repo.Commits.FirstOrDefault(c => c.Id.ToString() == commitID);
                    if (commit == null)
                        throw new Exception("提交未找到");

                    // 回滚到该提交
                    repo.Reset(ResetMode.Hard, commit);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"回滚失败: {ex.Message}", ex);
            }
        }

        public void Merge(ProjectTaskInformation rootTaskInformation, ProjectTaskInformation childTaskInformation)
{
    try
    {
        using (var repo = new Repository(rootTaskInformation.Path))
        {
            // 获取根任务和子任务的分支
            var rootBranch = repo.Branches[rootTaskInformation.BranchName];
            var childBranch = repo.Branches[childTaskInformation.BranchName];

            // 确保分支存在
            if (rootBranch == null || childBranch == null)
            {
                throw new InvalidOperationException("One or both branches not found.");
            }

            // 创建签名
            var signature = new Signature(rootTaskInformation.Name, rootTaskInformation.Name + "@example.com", DateTimeOffset.Now);

            // 合并子任务分支到根任务分支
            var mergeResult = repo.Merge(childBranch, signature, new MergeOptions
            {
                CommitOnSuccess = true
            });

            if (mergeResult.Status == MergeStatus.Conflicts)
            {
                Console.WriteLine("Merge conflict occurred. Please resolve conflicts and commit manually.");
            }
            else if (mergeResult.Status == MergeStatus.NonFastForward)
            {
                Console.WriteLine("Merge completed successfully with a merge commit.");
            }
            else if (mergeResult.Status == MergeStatus.FastForward)
            {
                Console.WriteLine("Merge completed successfully with a fast-forward.");
            }
            else if (mergeResult.Status == MergeStatus.UpToDate)
            {
                Console.WriteLine("Branch is already up to date.");
            }
            else
            {
                Console.WriteLine("Merge completed successfully.");
            }
        }
    }
    catch (Exception ex)
    {
        throw new Exception($"合并失败: {ex.Message}", ex);
    }
}

public void DeleteBranch(ProjectTaskInformation taskInformation)
{
    try
    {
        using (var repo = new Repository(taskInformation.Path))
        {
            // 获取要删除的分支名称
            string branchName = taskInformation.BranchName;

            // 删除分支
            repo.Branches.Remove(branchName);
            Console.WriteLine($"Branch {branchName} deleted successfully.");
        }
    }
    catch (Exception ex)
    {
        throw new Exception($"删除分支失败: {ex.Message}", ex);
    }
}
    }
}
